/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *                                                                           *
 *                          Copyright (c) 2010                               *
 *                  Alen Stojanov [ ioi.alen@gmail.com ]                     *
 *                Jacobs University Bremen, Bremen, Germany                  *
 *                                                                           *
 *                          All Rights Reserved.                             *
 *                                                                           *
 *    Permission to use, copy, modify and distribute this software and       *
 *    its documentation is hereby granted, provided that both the            *
 *    copyright notice and this permission notice appear in all copies of    *
 *    the software, derivative works or modified versions, and any           *
 *    portions thereof, and that both notices appear in supporting           *
 *    documentation.                                                         *
 *                                                                           *
 *    This code is distributed in the hope that it will be useful, but       *
 *    WITHOUT ANY WARRANTY; without even the implied warranty of             *
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS       *
 *    DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER          *
 *    RESULTING FROM THE USE OF THIS SOFTWARE.                               *
 *                                                                           *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#ifndef LSP_H
#define LSP_H

#include <QVector>

#include "tsdata.h"
#include "tspoint.h"
#include "matrix.h"

typedef math::matrix<double> TSMatrix;

class LSP
{

public:
	LSP(QVector<TSData*> ts);
	QVector<TSPoint> calculate (int controlPointsSize);
	QVector<int> getConnections();
	~LSP();

private:

	/**
	 * @brief	Main vector holding all points on which LSP will be applied
	 */
	QVector<TSData*> S;
	/**
	 * @brief	Vector holding all control points (not always in the same order as in S)
	 */
	QVector<TSData*> C;
	/**
	 * @brief	Map each control point to its neighborhood
	 */
	QMap <TSData*, QVector<TSData*> > V;
	/**
	 * @brief	The projection of the control points, obtained from MDP (must have the same order as C)
	 */
	QVector<TSPoint> CMDP;
	/**
	 * @brief	The complete projection of points
	 */
	QVector<TSPoint> projection;

	/**
	 * After the control points are found, and the neighborhood of each point is defined
	 * perform the LSP algorithm
	 */
	void lsp ();
	/**
	 * Calculate the alpha values on position i,j
	 */
	double alpha (int i, int j, QVector<TSData*>& V_i);

	/**
	 * @brief 	Perform Sammon's Mapping on given control points
	 *
	 * Sammon [Sam69] supposes a steepest-descent iterative process. This is computationally
	 * a havy task and quite complicated, on other hand Kohonen [Koh01] provides a heuristic
	 * that works reasonably well and is quite easy to implement.
	 *
	 * @param controlPoints		Set of given control points to perform Sammon's Mapping
	 * @return					Return the mapping of those points into 2D QPoints
	 */
	void sammon ();

	/**
	 * @brief Return a vector of control points using the naive Partitioning Around Medoids (PAM) method.
	 *
	 * The PAM method is the most easy and most intuitive and iterative method calculating k-medoids
	 * The algorythm can be described in 5 steps:
	 *
	 * 1. Initialize: randomly select k of the n data points as the medoids
	 * 2. Associate each data point to the closest medoid. ("closest" here is defined using
	 *    any valid distance metric, most commonly Euclidean distance, Manhattan distance or
	 *    Minkowski distance)
	 * 3. For each medoid m
	 * 		For each non-medoid data point o
	 * 			Swap m and o and compute the total cost of the configuration
	 * 4. Select the configuration with the lowest cost.
	 * 5. Repeat steps 2 to 5 until there is no change in the medoid.
	 *
	 * @param nc	The number of clusters
	 * @return		Vector of control points indexes corresponding to S
	 */
	void pam (int nc);
	/**
	 * @brief	Calculate given PAM configuration
	 */
	double pamConfCost (QVector<TSData*>& medois, QVector<TSData*>& non_medois);

	/**
	 * @brief	Calculate the neighborhood of each control point
	 */
	void getNeighbourhoods (QVector<TSData*>& controlPoints, QVector<TSData*>& non_controlPoints);
	/**
	 * @brief	Return a vector of random permutation of number 0 to size-1
	 */
	QVector<int> randomPermutationVector(int size);


};

#endif // LSP_H
